using System;
using System.Runtime.InteropServices;
using System.Text;

namespace CoreMobile.sec
{
public class DeviceInfo
{
private string _manufacture;
private string _model;
private string _revision;
private string _serialNumber; // IMEI
private string _subscriberID; // IMSI

public string Manufacture
{
get { return _manufacture; }
}

public string Model
{
get { return _model; }
}

public string Revision
{
get { return _revision; }
}

public string SerialNumber
{
get { return _serialNumber; }
}

public string SubscriberID
{
get { return _subscriberID; }
}

public DeviceInfo()
{
GetDeviceInfo();
}

private void GetDeviceInfo()
{
IntPtr hLine;
int dwNumDev;
int num1 = 0x20000;

LINEINITIALIZEEXPARAMS lineInitializeParams =  new
LINEINITIALIZEEXPARAMS();
lineInitializeParams.dwTotalSize = 
(uint)Marshal.SizeOf(lineInitializeParams);
lineInitializeParams.dwNeededSize = 
lineInitializeParams.dwTotalSize;
lineInitializeParams.dwUsedSize = 
lineInitializeParams.dwUsedSize;
lineInitializeParams.dwOptions =  2;
lineInitializeParams.hEvent =  IntPtr.Zero;
lineInitializeParams.hCompletionPort =  IntPtr.Zero;

// lineInitializeEx
int result =  NativeTapi.lineInitializeEx(out hLine,
IntPtr.Zero, IntPtr.Zero, null,
out dwNumDev, ref
num1, ref lineInitializeParams);
if (result !=  0)
{
//=20
//LogManager.GetLogger("DeviceInfo").Error(string.Format("lineInitializeEx
//failed!\n\nError Code: {0}", result.ToString()));
return;
}

// lineNegotiateAPIVerison
int version;
int dwAPIVersionLow =  0x10004;
int dwAPIVersionHigh =  0x20000;
LINEEXTENSIONID lineExtensionID;
result =  NativeTapi.lineNegotiateAPIVersion(hLine, 0,
dwAPIVersionLow, dwAPIVersionHigh, out version, out lineExtensionID);

if (result !=  0)
{
/*=20
LogManager.GetLogger("DeviceInfo").Error(string.Format("lineNegotiateAPIVer=
sion
failed!\n\nError Code:  {0}", result.ToString()));
*/return;
}

// lineOpen
IntPtr hLine2 =  IntPtr.Zero;
result =  NativeTapi.lineOpen(hLine, 0, out hLine2,
version, 0, IntPtr.Zero, 0x00000002, 0x00000004, IntPtr.Zero);

if (result !=  0)
{
/*=20
LogManager.GetLogger("DeviceInfo").Error(string.Format("lineNegotiateAPIVer=
sion
failed!\n\nError Code:  {0}", result.ToString()));
*/return;
}

// lineGetGeneralInfo
int structSize =  Marshal.SizeOf(new LINEGENERALINFO());
byte[] bytes =  new byte[structSize];
byte[] tmpBytes =  BitConverter.GetBytes(structSize);

for (int index =  0; index < tmpBytes.Length; index++)
{
bytes[index] =  tmpBytes[index];
}

// make initial query to retrieve necessary size
result =  NativeTapi.lineGetGeneralInfo(hLine2, bytes);

// get the needed size
int neededSize =  BitConverter.ToInt32(bytes, 4);

// resize the array
bytes =  new byte[neededSize];

// write out the new allocated size to the byte stream
tmpBytes =  BitConverter.GetBytes(neededSize);
for (int index =  0; index < tmpBytes.Length; index++)
{
bytes[index] =  tmpBytes[index];
}

// fetch the information with properly size buffer
result =  NativeTapi.lineGetGeneralInfo(hLine2, bytes);

if (result !=  0)
{
/*=20
LogManager.GetLogger("DeviceInfo").Error(Marshal.GetLastWin32Error().ToStri=
ng());
*/return;
}

int size;
int offset;

size =  BitConverter.ToInt32(bytes, 12);
offset =  BitConverter.ToInt32(bytes, 16);

// manufacture
if (size > 0 && offset > 0)
{
_manufacture =  Encoding.Unicode.GetString(bytes,
offset, size);
_manufacture =  _manufacture.Substring(0,
_manufacture.IndexOf('\0'));
}

size =  BitConverter.ToInt32(bytes, 20);
offset =  BitConverter.ToInt32(bytes, 24);

// model
if (size > 0 && offset > 0)
{
_model =  Encoding.Unicode.GetString(bytes, offset,
size);
_model =  _model.Substring(0, _model.IndexOf('\0'));
}

size =  BitConverter.ToInt32(bytes, 28);
offset =  BitConverter.ToInt32(bytes, 32);

// revision
if (size > 0 && offset > 0)
{
_revision =  Encoding.Unicode.GetString(bytes, offset,
size);
_revision =  _revision.Substring(0,
_revision.IndexOf('\0'));
}

size =  BitConverter.ToInt32(bytes, 36);
offset =  BitConverter.ToInt32(bytes, 40);

// serial number (IMEI)
if (size > 0 && offset > 0)
{
_serialNumber =  Encoding.Unicode.GetString(bytes,
offset, size);
_serialNumber =  _serialNumber.Substring(0,
_serialNumber.IndexOf('\0'));
}

size =  BitConverter.ToInt32(bytes, 44);
offset =  BitConverter.ToInt32(bytes, 48);

// subscriber id (IMSI)
if (size > 0 && offset > 0)
{
_subscriberID =  Encoding.Unicode.GetString(bytes,
offset, size);
_subscriberID =  _subscriberID.Substring(0,
_subscriberID.IndexOf('\0'));
}

// lineClose for hLine2
NativeTapi.lineClose(hLine2);

// lineShutdown for hLine
NativeTapi.lineShutdown(hLine);
}

[StructLayout(LayoutKind.Sequential)]
private struct LINEEXTENSIONID
{
public IntPtr dwExtensionID0;
public IntPtr dwExtensionID1;
public IntPtr dwExtensionID2;
public IntPtr dwExtensionID3;
}

[StructLayout(LayoutKind.Sequential)]
private struct LINEINITIALIZEEXPARAMS
{
public uint dwTotalSize;
public uint dwNeededSize;
public uint dwUsedSize;
public uint dwOptions;
public System.IntPtr hEvent;
public System.IntPtr hCompletionPort;
public uint dwCompletionKey;
}

[StructLayout(LayoutKind.Sequential)]
private struct LINEGENERALINFO
{
public int dwTotalSize;
public int dwNeededSize;
public int dwUsedSize;
public int dwManufacturerSize;
public int dwManufacturerOffset;
public int dwModelSize;
public int dwModelOffset;
public int dwRevisionSize;
public int dwRevisionOffset;
public int dwSerialNumberSize;
public int dwSerialNumberOffset;
public int dwSubscriberNumberSize;
public int dwSubscriberNumberOffset;
}

private class NativeTapi
{
[DllImport("coredll")]
public static extern int lineClose(IntPtr hLine);

[DllImport("cellcore")]
public static extern int lineGetGeneralInfo(IntPtr hLine,
byte[] bytes);

[DllImport("coredll")]
public static extern int lineGetAddressCaps(IntPtr
hLineApp, int dwDeviceID, int dwAddressID, int dwAPIVersion, int
dwExtVersion, byte[] lpAddressCaps);

[DllImport("coredll")]
public static extern int lineInitializeEx(out IntPtr
lpm_hLineApp, IntPtr hInstance, IntPtr lpfnCallback, string
lpszFriendlyAppName, out int lpdwNumDevs, ref int lpdwAPIVersion, ref
LINEINITIALIZEEXPARAMS lpLineInitializeExParams);

[DllImport("coredll")]
public static extern int lineNegotiateAPIVersion(IntPtr
m_hLineApp, int dwDeviceID, int dwAPILowVersion, int dwAPIHighVersion,
out int lpdwAPIVersion, out LINEEXTENSIONID lpExtensionID);

[DllImport("coredll")]
public static extern int lineOpen(IntPtr m_hLineApp, int
dwDeviceID, out IntPtr lphLine, int dwAPIVersion, int dwExtVersion,
IntPtr dwCallbackInstance, int dwPrivileges, int dwMediaModes, IntPtr
lpCallParams);

[DllImport("coredll")]
public static extern int lineShutdown(IntPtr m_hLineApp);
}
}
}